package top.jacktgq.concurrent_utils.pool;

import top.jacktgq.utils.LogUtils;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

/**
 * @Author CandyWall
 * @Date 2020/11/4--21:19
 * @Description Fork-join线程池测试
 */
public class ForkJoinDemo {
    public static void main(String[] args) {
        ForkJoinPool forkJoinPool = new ForkJoinPool(5);
        //System.out.println(forkJoinPool.invoke(new MyTask(5)));
        System.out.println(forkJoinPool.invoke(new AddTask(0, 5)));
    }
}

//求1~n之间整数的和
class MyTask extends RecursiveTask<Integer> {
    private int n;

    public MyTask(int n) {
        this.n = n;
    }

    @Override
    public String toString() {
        return "{" +
                "n=" + n +
                '}';
    }

    @Override
    protected Integer compute() {
        if (n == 1) {
            LogUtils.log("MyTask", "join(): " + n);
            return 1;
        }
        MyTask t1 = new MyTask(n - 1);
        //让一个线程去执行此任务
        t1.fork();
        LogUtils.log("MyTask", "fork(): " + n + " + " + t1);
        //返回最终结果
        int result = n + t1.join();
        LogUtils.log("MyTask", "join(): " + n + " + " + t1 + " = " + result);
        return result;
    }
}

//求1~n之间整数的和，改进拆分任务的手段，提高程序的并发度
class AddTask extends RecursiveTask<Integer> {
    private int begin;
    private int end;

    public AddTask(int begin, int end) {
        this.begin = begin;
        this.end = end;
    }

    @Override
    public String toString() {
        return "{" + begin + "," + end + '}';
    }

    @Override
    protected Integer compute() {
        if (begin == end) {
            LogUtils.log("AddTask", "fork() " + begin);
            return begin;
        }
        if (end - begin == 1) {
            LogUtils.log("AddTask", "join() " + begin + "+" + end + " = " + (end + begin));
            return end + begin;
        }

        int mid = (end + begin) / 2;
        AddTask t1 = new AddTask(begin, mid);
        t1.fork();
        AddTask t2 = new AddTask(mid + 1, end);
        t2.fork();

        int result = t1.join() + t2.join();
        LogUtils.log("AddTask", "fork() " + t1 + " + " + t2 + " = " + result);

        return result;
    }
}
